using System;

using Slaks.Descriptions;

namespace Slaks.Readers
{
	[ModuleDescriptionAttribute("TermBufferReader supports basic reading terms from buffered stream","Slava Kisilevich")]
	public class TermBufferReader : BufferReader
	{
		public TermBufferReader() {}
    public TermBufferReader(string buffer) : base(buffer) {}
    public TermBufferReader(Slaks.Filters.AFilter filter) : base(filter) {}
    public TermBufferReader(Slaks.Filters.AFilter filter,string buffer) : base(filter,buffer) {}

    public override string NextTerm(ref ReaderState state)
    {
      if (m_filter == null) throw new Exception("TermFilter must be registered first");
      string buffer = String.Empty;
      char ch;
      bool startTerm = false;
      bool endTerm = false;

      if (m_innerBuffer != char.MinValue) 
      {
        if ((m_isOutputPunctuationMarks && 
          (m_innerBufferState == ReaderState.MiddleSentencePunctuation || 
          m_innerBufferState == ReaderState.EndOfSentencePunctuation)) || 
          (m_isOutputSpecialCharacter && m_innerBufferState == ReaderState.SpecialCharacter))
        {
          ch = m_innerBuffer;
          m_innerBuffer = char.MinValue;
          state = m_innerBufferState;
          return ch.ToString();
        }else m_innerBuffer = char.MinValue;
      }

      while (!endTerm)
      {
        if (Eof()) break;

        ch = m_buffer[m_index++];

        //middle sentence punctuation mark
        if (m_filter.IsMiddleSentencePunctuationMark(ch)) 
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputPunctuationMarks) 
            {
              state = ReaderState.MiddleSentencePunctuation;
              return ch.ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch;
            m_innerBufferState = ReaderState.MiddleSentencePunctuation;
            state = ReaderState.Term;
            return buffer;
          }
        }

        //end of sentence punctuation mark
        if (m_filter.IsEndOfSentencePunctuationMark(ch)) 
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputPunctuationMarks) 
            {
              state = ReaderState.EndOfSentencePunctuation;
              return ch.ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch;
            state = ReaderState.Term;
            m_innerBufferState = ReaderState.EndOfSentencePunctuation;
            return buffer;
          }
        }

        //special character
        if (m_filter.IsSpecialCharacter(ch))
        {
          if (buffer == String.Empty) 
          {
            if (m_isOutputSpecialCharacter) 
            {
              state = ReaderState.SpecialCharacter;
              return ch.ToString();
            }
          }
          else 
          {
            m_innerBuffer = ch;
            state = ReaderState.Term;
            m_innerBufferState = ReaderState.SpecialCharacter;
            return buffer;
          }
        }

        ch = m_filter.Normalize(ch);

        if (!m_filter.DoSkipCharInTerm(ch) && !m_filter.IsWhiteSpace(ch))
        {
          buffer += ch;
          if (!startTerm) startTerm = true;
        }

        if (m_filter.IsWhiteSpace(ch)) 
        {
          if (startTerm) endTerm = true;
        }
      }

      if (buffer == String.Empty) 
      {
        if (m_innerBuffer != char.MinValue) 
        {
          state = m_innerBufferState;
          return m_innerBuffer.ToString();
        }
        state = ReaderState.None;
      }
      else state = ReaderState.Term;
      return buffer;
    }
	}
}
